package com.gdepri.cabelwellserver.tools;
import com.github.misterchangray.core.util.ConverterUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.UnsupportedEncodingException;

public class ByteFun {
    private Logger logger = LoggerFactory.getLogger(ByteFun.class);
    /**
     * 从一个完整的报文数组中,找到关于长度的报文,也就是位于第1个字节之后的连续2个字节,表示长度。长度是3+N,
     * 其中3是控制字(2字节)+地址(1字节),N是数据的长度
     * @param msgByteArr 一个完整的报文数组
     * @return 长度的int值
     */
    public  int findLenByteArrFromMsgByteArr(byte[] msgByteArr){
        byte[] lengthByteArr = new byte[2];//剩下的数组的长度
        System.arraycopy(msgByteArr,1,lengthByteArr,0,2);

        //把lengthByteArr的顺序倒置
        for(int i=0;i<lengthByteArr.length/2;i++){
            byte temp = lengthByteArr[i];
            lengthByteArr[i] = lengthByteArr[lengthByteArr.length-1-i];
            lengthByteArr[lengthByteArr.length-1-i] = temp;
        }

        String s = pasreByte2Binary(lengthByteArr);
        logger.info("长度的二进制"+s);
        int lenth = Integer.parseInt(s, 2);
        logger.info("长度"+lenth);
        return lenth;
    }


    /**
     * 把字节数组转换为2进制,传入的参数中,其中的每个byte表示一个字节，也就是8位的比特。
     * 如果传进来一个2字节的byte数组,那么就会得到一个16位的2进制数组
     * @param ctrl byte数组
     * @return
     */
    public static String pasreByte2Binary(byte[] ctrl){
        StringBuffer sb = new StringBuffer();
        for(int i=0;i<ctrl.length;i++){
            sb.append(String.format("%8s", Integer.toBinaryString(ctrl[i] & 0xFF)).replace(' ', '0'));
        }
        return sb.toString();
    }

    /**
     * 以16进制打印byte数组
     * @param arr
     */
    public  String print16ByteArr(byte[] arr){
        String s = ConverterUtil.byteToHexString(arr);
        StringBuffer sb = new StringBuffer();
        for(int i=0;i<s.length();i++){
            sb.append(s.charAt(i));
            if(i%2!=0){
                sb.append(" ");
            }
        }
        return sb.toString();
    }

    /**
     * 专属打印,打印16进制的报文
     * @param arr
     */
    public  String print16ByteArrByLength(byte[] arr,int n){
        String s = ConverterUtil.byteToHexString(arr);
        int count = 0;
        StringBuffer sb = new StringBuffer();
        sb.append(" 起始字");
        for(int i=0;i<s.length();i++){
            sb.append(s.charAt(i));
            if(i%2!=0){
                sb.append(" ");
                count++;
                if(count==1){
                    sb.append(" 长度");
                }else if (count==3){
                    sb.append(" 控制字");
                }else if (count==4){
                    sb.append(" 地址");
                }else if (count==6){
                    sb.append(" 数据");
                }else if (count==6+n){
                    sb.append(" 校验码");
                }else if (count==7+n){
                    sb.append(" 结束符");
                }
            }
        }
        return sb.toString();
    }

    /**
     * 单个的字节转换成8位二进制字符串
     * @param ctrl 单个的字节
     * @return
     */
    public static String pasreByte2Binary(byte ctrl){
        StringBuffer sb = new StringBuffer();
        sb.append(String.format("%8s", Integer.toBinaryString(ctrl & 0xFF)).replace(' ', '0'));
        return sb.toString();
    }

    /**
     * 根据传入大小为2的byte数组,来解析出值
     * @param msgByteArr
     * @return
     */
    public  int findAddressByteArrFromMsgByteArr(byte[] msgByteArr){
        byte[] addressByteArr = new byte[2];//剩下的数组的长度
        System.arraycopy(msgByteArr,4,addressByteArr,0,2);

        //把addressByteArr的顺序倒置
        for(int i=0;i<addressByteArr.length/2;i++){
            byte temp = addressByteArr[i];
            addressByteArr[i] = addressByteArr[addressByteArr.length-1-i];
            addressByteArr[addressByteArr.length-1-i] = temp;
        }

        String s = pasreByte2Binary(addressByteArr);
        logger.info("地址的二进制"+s);
        int address = Integer.parseInt(s, 2);
        logger.info("  地址"+address);
        return address;
    }

    /**
     * 从报文中找到数据的部分，返回
     * @param msgByteArr 完整的消息报文
     * @param datalength 数据的byte
     * @return
     */
    public static byte[] findDataByteArrFromMsgByteArr(byte[] msgByteArr,int datalength){
        byte[] dataByteArr = new byte[datalength];
        System.arraycopy(msgByteArr,6,dataByteArr,0,datalength);
        return dataByteArr;
    }


    /**
     * 也有可能不太对，因为这个byte明显是有符号的
     * @param bytes
     * @return
     */
    public static int checkByteArr(byte[] bytes) {
        int n = 0;
        for (int i = 3; i < bytes.length-2; i++) {
            int counter = Byte.toUnsignedInt(bytes[i]);
            n += counter;
        }
        return n;
    }

    /**
     * int型转换成byte型数组
     * Java中，一个int型占用4个字节，一个byte型占用1个字节，所以，对于一个int型，我们需要一个长度为4的byte型数组来对其进行存储
     * 这里需要注意的是，当你将一个int型强制类型转换为byte型的时候，最高的三个字节会被砍掉，只留下最低的8位赋值给byte型
     *
     * @param integer
     * @return
     */
    public static byte[] intTo4Bytes(int integer)
    {
        byte[] bytes=new byte[4];
        bytes[0]=(byte) (integer>>24);
        bytes[1]=(byte) (integer>>16);
        bytes[2]=(byte) (integer>>8);
        bytes[3]=(byte) (integer);
        return bytes;
    }

    public static byte[] intTo2Bytes(int integer)
    {
        byte[] bytes=new byte[2];
        bytes[1]=(byte) (integer>>8);
        bytes[0]=(byte) (integer);
        return bytes;
    }

    /**
     * byte型数组转换成int型
     *计算机是以补码的形式存放数值型数据，当我们对一个byte型进行移位操作的时候，这个byte型会先自动补全到32位（即一个int型）,
     * 再进行移位操作。举个例子：一个byte型的-1，在内存中的补码是八个1：11111111，当我们进行移位时,
     * （比如说左移8位），它会进行补全，而且是有符号位的补全，再左移8位，
     * 所以最后结果是：11111111 11111111 11111111 00000000，
     * 但我们因为最后在将byte型数组转换成int型的时候，需要对数组元素使用按位或（ | ）操作，
     * 因此，移位结果前面的符号位如果不去除，将影响我们的运算，得出一个错误的结果。
     * （上例中我们左移8位，需要将11111111 11111111 11111111 00000000去掉前面的那些1，
     * 只保留次低位上的1，即为：0000000000000000 11111111 00000000）。
     * 我们可以先将byte数据元素与0xff（二进制的00000000 00000000 00000000 11111111）
     * 进行按位与运算（ & ），再进行移位，来去除前面的符号位。byte型数组转换成int型的代码如下
     * @param bytes
     * @return
     */
    public static int bytes2Int(byte[] bytes )
    {
        //如果不与0xff进行按位与操作，转换结果将出错，有兴趣的同学可以试一下。
        int int1=bytes[3]&0xff;
        int int2=(bytes[2]&0xff)<<8;
        int int3=(bytes[1]&0xff)<<16;
        int int4=(bytes[0]&0xff)<<24;

        return int1|int2|int3|int4;
    }


//    public static String pasreByte2Binary(byte ctrl){
//        StringBuffer sb = new StringBuffer();
//        sb.append(String.format("%8s", Integer.toBinaryString(ctrl & 0xFF)).replace(' ', '0'));
//        return sb.toString();
//    }

    /**
     * 一个int值转换成2位的二进制字符串
     * @param n
     * @return
     */
    public static String int2binary2(int n){
        StringBuffer sb = new StringBuffer();
        sb.append(String.format("%2s", Integer.toBinaryString(n & 0xFF)).replace(' ', '0'));
        String s = sb.toString();
        if(s.length()>2){
            s = s.substring(s.length()-2,s.length());
        }
        return s;
    }

    /**
     * 一个int值转换成5位的二进制字符串
     * @param n
     * @return
     */
    public static String int2binary5(int n){
        StringBuffer sb = new StringBuffer();
        sb.append(String.format("%5s", Integer.toBinaryString(n & 0xFF)).replace(' ', '0'));
        return sb.toString();
    }

    public static String byteArr2String(byte[] arr) throws UnsupportedEncodingException {
        if(arr==null || arr.length>0){
            arr = new byte[0];
        }
        return new String(arr,"ISO-8859-1");
    }

    public static byte[] String2ByteArr(String str) throws UnsupportedEncodingException {
        byte[] bytes = str.getBytes("ISO-8859-1");
        return  bytes;
    }

    /**
     * 得到地址 从[78,0]得到值 00000000 1001110 得到78
     * @param lift 比如78
     * @param right 比如0
     * @return 得到78
     */
    public static int getAddress(byte lift,byte right){
        int int1=lift&0xff;
        int int2=(right&0xff)<<8;
        return int1|int2;
    }

    /**
     * 从数组中得到数据
     * @param arr 数组
     * @param begin 起始下标(包含)
     * @param end  结束下标(不包含)
     * @return
     */
    public static int getDataFromArrByIndex(byte[] arr,int begin,int end){
             //打印begin到end的值
        System.out.println("begin:"+begin+"  "+"end:"+end);
             for(int i=begin;i<end;i++){
                 System.out.print(arr[i]+" ");
             }

             int len = end-begin;
             int res = 0;
             if(len ==1){
                 res =  arr[begin]&0xff;
             }else if(len ==2){
                 res =  (arr[begin]&0xff) | (arr[begin+1]&0xff)<<8;
             }else if(len ==4){
                 res =  (arr[begin]&0xff) | (arr[begin+1]&0xff)<<8 | (arr[begin+2]&0xff)<<16 | (arr[begin+3]&0xff)<<24;
             }else if(len ==8){
                 res =  (arr[begin]&0xff) | (arr[begin+1]&0xff)<<8 | (arr[begin+2]&0xff)<<16 | (arr[begin+3]&0xff)<<24
                         | (arr[begin+4]&0xff)<<32 | (arr[begin+5]&0xff)<<40 | (arr[begin+6]&0xff)<<48 | (arr[begin+7]&0xff)<<56;
             }
             return res;
    }

    public static float getFloatBy4Bytes(byte a,byte b,byte c,byte d){
        //float foo = Float.intBitsToFloat( buffer[n] ^ buffer[n+1]<<8 ^ buffer[n+2]<<16 ^ buffer[n+3]<<24 );
        float foo = Float.intBitsToFloat( a ^ b<<8 ^ c<<16 ^ d<<24 );
        return foo;
    }
}
